package persistence

import (
	"sync"
	"time"
)

type MemoryContainer struct {
	msgLock    sync.Mutex
	userLock   sync.Mutex
	msgMap     map[string]*OfflineMsg
	userMsgMap map[string][]string
}

func (this *MemoryContainer) Get(id string) (*OfflineMsg, error) {
	this.msgLock.Lock()
	defer this.msgLock.Unlock()
	if v, ok := this.msgMap[id]; ok {
		delete(this.msgMap, id)
		return v, nil
	}
	return nil, Err_MsgNotFound
}

func (this *MemoryContainer) GetUserMsg(userId string) ([]*OfflineMsg, error) {
	this.userLock.Lock()
	msgs, ok := this.userMsgMap[userId]
	delete(this.userMsgMap, userId)
	this.userLock.Unlock()

	if !ok {
		return nil, Err_MsgNotFound
	}

	msgColl := make([]*OfflineMsg, 0)
	for _, id := range msgs {
		if v, err := this.Get(id); err == nil {
			msgColl = append(msgColl, v)
		}
	}
	if len(msgColl) > 0 {
		return msgColl, nil
	} else {
		return nil, Err_MsgNotFound
	}
}

func (this *MemoryContainer) Put(msg *OfflineMsg) {
	this.msgLock.Lock()
	this.userLock.Lock()
	defer func() {
		this.msgLock.Unlock()
		this.userLock.Unlock()
	}()
	user := msg.To
	if u, ok := this.userMsgMap[user]; ok {
		this.userMsgMap[user] = append(u, msg.MsgId)
	} else {
		this.userMsgMap[user] = []string{msg.MsgId}
	}
	this.msgMap[msg.MsgId] = msg
}

func (this *MemoryContainer) gc(interval int) {
	go func(interval int) {
		for {
			invalid := make([]string, 0)
			this.msgLock.Lock()
			for key := range this.msgMap {
				if this.msgMap[key].KeepLiveTime.Before(time.Now()) {
					invalid = append(invalid, key)
				}
			}
			if len(invalid) > 0 {
				for _, k := range invalid {
					delete(this.msgMap, k)
				}
			}
			this.msgLock.Unlock()
			time.Sleep(time.Duration(interval) * time.Millisecond)
		}
	}(interval)
}
